home *** CD-ROM | disk | FTP | other *** search
-
- type
- str10 = string[10];
-
- const
-
- hx:array[0..15] of char='0123456789ABCDEF';
-
- Debug:boolean=false; {If set step through video tests one by one}
- Auto_test:boolean=false; {If set run tests automatically}
-
-
- {Keys:}
- Ch_Cr = $0D;
- Ch_Esc = $1B;
- Ch_F1 = $13B;
- Ch_F2 = $13C;
- Ch_F3 = $13D;
- Ch_F4 = $13E;
- Ch_F5 = $13F;
- Ch_F6 = $140;
- Ch_F7 = $141;
- Ch_F8 = $142;
- Ch_Home = $147;
- Ch_ArUp = $148;
- Ch_PgUp = $149;
- Ch_ArLeft = $14B;
- Ch_ArRight = $14D;
- Ch_End = $14F;
- Ch_ArDown = $150;
- Ch_PgDn = $151;
- Ch_Ins = $152;
- Ch_Del = $153;
-
-
- {Standard segment defines}
- Seg0000 = $0000; {Interupt table}
- Seg0040 = $0040; {BIOS data segment}
- SegA000 = $A000; {Graphics Video buffer}
- SegA800 = $A800; {Graphics Video buffer - upper half}
- SegB000 = $B000; {Mono Text mode buffer}
- SegB800 = $B800; {Color Text mode buffer}
- SegC000 = $C000; {BIOS ROM segment}
-
- {Gamma correction types}
- GAM_None = 0; {No Gamma correction}
- GAM_CanDo = 1; {}
- GAM_LeftJ = 2; {left justify Red&Blue 1bit each}
- GAM_Left8 = 4; {Left justify to 8bits}
- GAM_8bit = 8; {DAC Gamma registers are 8bit (not 6)}
-
- type
- CursorType=Array[0..31] of longint; {32 lines of 32 pixels}
- charr =array[1..255] of char;
- chptr =^charr;
-
-
- var
- rp:registers;
-
- video:string[20];
- _crt:string[20];
- secondary:string[20];
-
- planes:word; {number of video planes}
-
-
- dacHWcursor:boolean; {True if we use the DAC cursor, rather than the VGA one}
-
-
- vseg:word; {Video buffer base segment}
- biosseg:word;
-
- curmode:word; {Current mode number}
- memmode:byte; {current memory mode}
- crtc:word; {I/O address of CRTC registers}
- pixels:word; {Pixels in a scanline in current mode}
- lins:word; {lines in current mode}
- bytes:longint; {bytes in a scanline}
-
- force_chip:byte;
- force_mm:word; {Forced memory size in Kbytes}
- force_version:word; {Forced chip version}
- clocktest:boolean; {Set false to disable clocktesting.}
-
-
- extpixfact:word; {The number of times each pixel is shown}
- extlinfact:word; {The number of times each scan line is shown}
- charwid :word; {Character width in pixels}
- charhigh :word; {Character height in scanlines}
- calcvseg:word;
- calcpixels, {Calculated displayed pixels per scanline}
- calclines, { " displayed scanlines}
- calchtot, { " total pixels/scanline}
- calcvtot, { " total lines/frame}
- calchblks, { " Hor. Blanking Start}
- calchblke, { " Hor Blanking End (see hblkmask)}
- calchrtrs, { " Hor Retrace Start}
- calchrtre, { " Hor Retrace End (see hrtrmask)}
- calcvblks, { " Vert Blanking Start}
- calcvblke, { " Vert Blanking End (see vblkmask)}
- calcvrtrs, { " Vert Retrace Start}
- calcvrtre, { " Vert Retrace End (see vrtrmask)}
- hblkmask, { " }
- hrtrmask, { " }
- vblkmask, { " }
- vrtrmask, { " }
- calcbytes:word;
- calcmmode:byte;
-
-
- vclk,hclk,fclk:longint; {Pixel (kHz), Line (Hz) & Frame (mHz) clocks}
- ilace:boolean;
-
-
- daccomm:word; {The result of the last dac2comm}
-
-
- BWlow,BWhigh:longint; {Bandwidth requirement - low & high in Kbytes/sec}
-
-
- (* Interface declarations for functions. In DEFVGA.PAS *)
-
-
- (* Utility & User interfrace functions*)
- procedure disable; {Disable interupts}
-
- procedure enable; {Enable interrupts}
-
- function gtstr(var cp:char):string;
-
- function getkey:word; {Waits for a key, and returns the keyID}
-
- function peekkey:word; {Checks for a key, and returns the keyID}
-
- procedure pushkey(k:word); {Simulates a keystroke}
-
- {Pretend the last key was pushed again}
- procedure repeatkey;
-
- function strip(s:string):string; {strip leading and trailing spaces}
-
- function upstr(s:string):string; {convert a string to upper case}
-
- function istr(w:longint):str10; {convert number to string}
-
- function dehex(s:string):longint; {Hex string to number}
-
- function hex2(w:word):str10; {convert number to 2digit hex string}
-
- function hex4(w:word):str10; {convert number to 4digit hex string}
-
- function hex8(w:longint):str10; {convert number to 4digit hex string}
-
- procedure swapbyte(var a,b:byte); {Swap the 2 bytes}
-
- function clipstr(var s:string):string; {Cuts & returns the first non-space
- substring from s}
-
- {BIOS & lowlevel I/O functions}
-
- procedure vio(ax:word); {INT 10h reg ax=AX. other reg. set from RP
- on return rp.ax=reg AX}
-
- procedure viop(ax,bx,cx,dx:word;p:pointer);
- {INT 10h reg AX-DX, ES:DI = p}
-
- function inp(reg:word):byte; {Reads a byte from I/O port REG}
-
- function inpw(reg:word):word; {Reads a word from I/O port REG}
-
- function inpl(reg:word):longint; {Reads a DWORD from I/O port REG}
-
- procedure outp(reg,val:word); {Write the low byte of VAL to I/O port REG}
-
- procedure outpw(reg,val:word); {Write the word byte of VAL to I/O port REG}
-
- procedure outpl(reg:word;val:longint); {Write the word byte of VAL to I/O port REG}
-
- {Outputs a 32bit value as a single OUT DX,EAX - requires 386 or better}
- procedure outplong(reg:word;val:longint);
-
- {Inputs a 32bit value as a single IN EAX,DX - requires 386 or better}
- function inplong(reg:word):longint;
-
-
- function rdinx(pt,inx:word):word; {read register PT index INX}
-
- procedure wrinx(pt,inx,val:word); {write VAL to register PT index INX}
-
- procedure wrinx2(pt,inx,val:word); {write VAL to register PT index INX}
-
- procedure wrinx2m(pt,inx,val:word); {write VAL to register PT index INX}
-
- procedure wrinx3(pt,inx:word;val:longint); {write VAL to register PT index INX}
-
- procedure wrinx3m(pt,inx:word;val:longint); {write VAL to register PT index INX}
-
- procedure modinx(pt,inx,mask,nwv:word); {In register PT index INX sets
- the bits in MASK as in NWV
- the other are left unchanged}
-
- procedure setinx(pt,inx,val:word);
-
- procedure clrinx(pt,inx,val:word);
-
- procedure modreg(reg,mask,nwv:word); {In register PT index INX sets
- the bits in MASK as in NWV
- the other are left unchanged}
-
- procedure setreg(reg,val:word);
-
- procedure clrreg(reg,val:word);
-
- procedure modregw(reg,mask,nwv:word); {In register PT index INX sets
- the bits in MASK as in NWV
- the other are left unchanged}
-
- procedure setregw(reg,val:word);
-
- procedure clrregw(reg,val:word);
-
- {Lowlevel DAC stuff}
- function trigdac:word; {Reads $3C6 4 times}
-
- procedure setDACstd;
- procedure setdac8(on:boolean);
- function setdac15:boolean;
- function setdac16:boolean;
- function setdac24:boolean;
- function setdac32:boolean;
-
- function setDACgamma(on:boolean):word;
-
-
- function setDACpage(index:word):word;
-
- procedure clearDACpage;
-
- function rdDACreg(index:word):word;
-
- procedure wrDACreg(index,val:word);
-
- procedure clrDACreg(index,val:word);
-
- procedure setDACreg(index,val:word);
-
- procedure modDACreg(index,msk,val:word);
-
-
- function getdaccomm:word;
-
- procedure dac2comm;
-
- procedure dac2pel;
-
-
- {Probe clocks, should really be in IDVGA ??}
- procedure findclocks;
-
-
- {The LOG functions writes output data to both the screen and the file
- WHATVGA.TXT, to provide a log in case of lockup}
-
- procedure openlog(scr:boolean);
-
- procedure wrlog(s:string);
-
- procedure closelog;
-
-
-
-
-
- (* HW cursor, BitBLT, linedraw and clock function in BITBLT.PAS *)
-
- procedure setHWcurmap(VAR map:CursorType);
-
- procedure HWcuronoff(on:boolean);
-
- procedure setHWcurpos(X,Y:word);
-
- procedure setHWcurcol(fgcol,bkcol:longint);
-
-
- procedure setZoomWindow(Xs,Ys,Xe,Ye:word);
-
- procedure setZoomAdr(AdrX,AdrY:word);
-
- procedure ZoomOnOff(On:boolean);
-
- procedure setZoomFactor(Fx,Fy:word);
-
- procedure vesamodeinfo(md:word;var vbedata);
-
-
- procedure fillrect(xst,yst,dx,dy:word;col:longint);
-
- procedure copyrect(srcX,srcY,dstX,dstY,dx,dy:word);
-
- procedure line(x0,y0,x1,y1:integer;col:longint);
-
- procedure setclk(Nbr,divi:word);
-
- function getclk(var divisor,divid:word):word;
-
- function getClockFreq:longint; {Effective pixel clock in kHz}
-
-
-
-
- (* Bank, mode and Vstart rutines, in SUPERVGA.PAS *)
-
- procedure setbank(bank:word);
-
- procedure setRbank(bank:word);
-
- procedure setvstart(x,y:word); {Set the display start to (x,y)}
-
- function setmode(md:word;clear:boolean):boolean;
-
- procedure SetTextMode;
-
-
-
- procedure SetRGBPal(inx,r,g,b:word);
-
- procedure SelectVideo(Item:word);
-
- function rgb(r,g,b:word):longint; {Converts RGB values to pixel in the
- current pixelformat }
-
- {Returns the pixel BIT address}
- function pixeladdress(x,y:word):longint;
-
- implementation
- uses idvga;
-
-
- var
-
- clocktbl:array[0..31] of longint;
-
-
- procedure disable; (* Disable interupts *)
- begin
- inline($fa); (* CLI instruction *)
- end;
-
-
- procedure enable; (* Enable interrupts *)
- begin
- inline($fb); (* STI instruction *)
- end;
-
-
- function gtstr(var cp:char):string;
- var x:word;
- s:string;
- str:chptr;
- begin
- str:=chptr(@cp);
- s:='';x:=1;
- if str<>NIL then
- while (x<255) and (str^[x]<>#0) do
- begin
- if str^[x]<>#7 then s:=s+str^[x];
- inc(x);
- end;
- gtstr:=s;
- end;
-
- const
- key_stack:word=0; {Stored key stroke 0=none}
- lastkey:word=0;
-
- function getkey:word;
- var c:char;
- begin
- if key_stack<>0 then
- begin
- lastkey:=key_stack;
- key_stack:=0;
- end
- else begin
- c:=readkey;
- if c=#0 then lastkey:=$100+ord(readkey)
- else lastkey:=ord(c);
- end;
- getkey:=lastkey;
- end;
-
- function peekkey:word;
- begin
- if (key_stack=0) and not keypressed then peekkey:=0
- else peekkey:=getkey;
- end;
-
- procedure pushkey(k:word); {Simulates a key stroke}
- var ch:char;
- begin
- key_stack:=k;
- while keypressed do ch:=readkey;
- end;
-
- {Pretend the last key was pushed again}
- procedure repeatkey;
- begin
- pushkey(lastkey);
- end;
-
- {Swap the 2 bytes}
- procedure swapbyte(var a,b:byte);
- var c:byte;
- begin
- c:=a;
- a:=b;
- b:=c;
- end;
-
-
- function strip(s:string):string; {strip leading and trailing spaces}
- begin
- while s[length(s)]=' ' do dec(s[0]);
- while copy(s,1,1)=' ' do delete(s,1,1);
- strip:=s;
- end;
-
- function upstr(s:string):string; {convert a string to upper case}
- var x:word;
- begin
- for x:=1 to length(s) do
- s[x]:=upcase(s[x]);
- upstr:=s;
- end;
-
- function istr(w:longint):str10;
- var s:str10;
- begin
- str(w,s);
- istr:=s;
- end;
-
-
- function hex2(w:word):str10;
- begin
- hex2:=hx[(w shr 4) and 15]+hx[w and 15];
- end;
-
- function hex4(w:word):str10;
- begin
- hex4:=hex2(hi(w))+hex2(lo(w));
- end;
-
- function hex8(w:longint):str10;
- begin
- hex8:=hex4(w shr 16)+hex4(w);
- end;
-
- function dehex(s:string):longint;
- var x:word;
- l:longint;
- c:char;
- begin
- l:=0;
- for x:=1 to length(s) do
- begin
- c:=s[x];
- case c of
- '0'..'9':l:=(l shl 4)+(ord(c) and 15);
- 'a'..'f','A'..'F':
- l:=(l shl 4)+(ord(c) and 15 +9);
- end;
- end;
- dehex:=l;
- end;
-
- function clipstr(var s:string):string; {Cuts & returns the first non-space
- substring from s}
- var
- i:integer;
- begin
- i:=0;
- while s[i+1]=' ' do inc(i);
- delete(s,1,i);
- i:=0;
- while (i<length(s)) and (s[i+1]>' ') do inc(i);
- clipstr:=copy(s,1,i);
- delete(s,1,i);
- end;
-
-
- procedure vio(ax:word); {INT 10h reg ax=AX. other reg. set from RP
- on return rp.ax=reg AX}
- begin
- rp.ax:=ax;
- intr($10,rp);
- end;
-
- procedure viop(ax,bx,cx,dx:word;p:pointer);
- begin {INT 10h reg AX-DX, ES:DI = p}
- rp.ax:=ax;
- rp.bx:=bx;
- rp.cx:=cx;
- rp.dx:=dx;
- rp.di:=ofs(p^);
- rp.es:=seg(p^);
- intr($10,rp);
- end;
-
- function inp(reg:word):byte; {Reads a byte from I/O port REG}
- begin
- reg:=port[reg];
- inp:=reg;
- end;
-
-
- function inpw(reg:word):word; {Reads a word from I/O port REG}
- begin
- reg:=portw[reg];
- inpw:=reg;
- end;
-
- function inpl(reg:word):longint; {Reads a word from I/O port REG}
- var l:longint;
- begin
- l:=portw[reg];
- inpl:=l+(longint(portw[reg+2]) shl 16);
- end;
-
- {Inputs a 32bit value as a single IN EAX,DX - requires 386 or better}
- function inplong(reg:word):longint;
- var l:longint;
- begin
- inline($8B/$56/<reg/$66/$ED/$66/$89/$46/<l);
- inplong:=l;
- end;
-
- procedure outp(reg,val:word); {Write the low byte of VAL to I/O port REG}
- begin
- port[reg]:=val;
- end;
-
- procedure outpw(reg,val:word);
- begin
- portw[reg]:=val;
- end;
-
- procedure outpl(reg:word;val:longint); {Write the Dword of VAL to I/O port REG}
- begin
- portw[reg] :=val;
- portw[reg+2]:=val shr 16;
- end;
-
- {Outputs a 32bit value as a single OUT DX,EAX - requires 386 or better}
- procedure outplong(reg:word;val:longint);
- begin
- {mov dx,[BP+reg] mov eax,[BP+val] out dx,eax}
- inline($8B/$56/<reg/$66/$8B/$46/<val/$66/$EF);
- end;
-
-
- function rdinx(pt,inx:word):word; {read register PT index INX}
- var x:word;
- begin
- if pt=$3C0 then
- begin
- x:=inp(CRTC+6); {Reset Attribute Data/Address Flip-Flop}
- outp($3C0,inx and $DF); {Clear bit 5 of index}
- for x:=1 to 10 do;
- rdinx:=inp($3C1); {delay}
- x:=inp(CRTC+6); {Reset Attribute Data/Address Flip-Flop}
- for x:=1 to 10 do; {delay}
- outp($3C0,$20); {Set index bit 5 to keep display alive}
- x:=inp(CRTC+6); {Reset Attribute Data/Address Flip-Flop}
- end
- else begin
- outp(pt,inx);
- rdinx:=inp(pt+1);
- end;
- end;
-
- procedure wrinx(pt,inx,val:word); {write VAL to register PT index INX}
- var x:word;
- begin
- if pt=$3C0 then
- begin
- x:=inp(CRTC+6);
- outp($3C0,inx and $DF);
- outp($3C0,val);
- x:=inp(CRTC+6); {If Attribute Register then reset Flip-Flop}
- outp($3C0,$20);
- x:=inp(CRTC+6);
- end
- else begin
- outp(pt,inx);
- outp(pt+1,val);
- end;
- end;
-
- procedure wrinx2(pt,inx,val:word);
- begin
- wrinx(pt,inx,lo(val));
- wrinx(pt,inx+1,hi(val));
- end;
-
- procedure wrinx3(pt,inx:word;val:longint);
- begin
- wrinx(pt,inx,lo(val));
- wrinx(pt,inx+1,hi(val));
- wrinx(pt,inx+2,val shr 16);
- end;
-
- procedure wrinx2m(pt,inx,val:word); {Write VAL to the index pair (INX,INX+1)}
- begin {in motorola (big endian) format}
- wrinx(pt,inx,hi(val));
- wrinx(pt,inx+1,lo(val));
- end;
-
- procedure wrinx3m(pt,inx:word;val:longint);
- begin
- wrinx(pt,inx+2,lo(val));
- wrinx(pt,inx+1,hi(val));
- wrinx(pt,inx,val shr 16);
- end;
-
- procedure modinx(pt,inx,mask,nwv:word); {In register PT index INX sets
- the bits in MASK as in NWV
- the other are left unchanged}
- var temp:word;
- begin
- temp:=(rdinx(pt,inx) and (not mask))+(nwv and mask);
- wrinx(pt,inx,temp);
- end;
-
- procedure modreg(reg,mask,nwv:word); {In register REG sets the bits in
- MASK as in NWV other are left unchanged}
- var temp:word;
- begin
- temp:=(inp(reg) and (not mask))+(nwv and mask);
- outp(reg,temp);
- end;
-
-
- procedure setinx(pt,inx,val:word);
- var x:word;
- begin
- x:=rdinx(pt,inx);
- wrinx(pt,inx,x or val);
- end;
-
- procedure clrinx(pt,inx,val:word);
- var x:word;
- begin
- x:=rdinx(pt,inx);
- wrinx(pt,inx,x and (not val));
- end;
-
- procedure setreg(reg,val:word);
- begin
- outp(reg,inp(reg) or val);
- end;
-
- procedure clrreg(reg,val:word);
- begin
- outp(reg,inp(reg) and (not val));
- end;
-
- procedure modregw(reg,mask,nwv:word); {In register REG sets the bits in
- MASK as in NWV other are left unchanged}
- var temp:word;
- begin
- temp:=(inpw(reg) and (not mask))+(nwv and mask);
- outpw(reg,temp);
- end;
-
- procedure setregw(reg,val:word);
- begin
- outpw(reg,inpw(reg) or val);
- end;
-
- procedure clrregw(reg,val:word);
- begin
- outpw(reg,inpw(reg) and (not val));
- end;
-
-
- {The LOG functions writes output data to both the screen and the file
- WHATVGA.TXT, to provide a log in case of lockup}
- var
- logfile:text;
- wrscr:boolean;
-
- procedure openlog(scr:boolean);
- begin
- assign(logfile,'whatvga.txt');
- rewrite(logfile);
- wrscr:=scr;
- if scr then SetTextMode;
- end;
-
- procedure wrlog(s:string);
- begin
- if wrscr then writeln(s);
- writeln(logfile,s);
- end;
-
- procedure closelog;
- begin
- close(logfile);
- end;
-
-
-
-
- {Select the mode to use for the clock test, preferable a 25.175MHz one!
- Returns the frequency (in kHz for the base freq}
- function setstdmode:longint;
- var md:integer;
- begin
- setstdmode:=25175;
- case cv.chip of
- __Mach32:md:=$321;
- __Mach64:begin
- md:=$1292;
- setstdmode:=28322;
- end;
- { __Compaq:if cv.version>=CPQ_QV then md:=$32
- else md:=$12; }
- __AGX:begin
- md:=$64;
- setstdmode:=44900;
- end;
- else md:=$12;
- end;
- if setmode(md,false) then;
- end;
-
-
- function Vretrace:boolean;
- begin
- case cv.chip of
- __Mach64:VRetrace:=memw[cv.Xseg:$12]>=memw[cv.Xseg:$0A];
- __Mach32:VRetrace:=inpw($CEEE)>=inpw($CAEE); {Hm!!}
- __AGX:if (inp(cv.IOadr+5) and 1)>0 then
- begin
- outp(cv.IOadr+5,1); {Reset blanking flag}
- VRetrace:=true;
- end
- else Vretrace:=false;
- else
- VRetrace:=(inp(crtc+6) and 8)>0; {3D4h/3B4h}
- end;
- end;
-
-
- function getticks:longint;
- var cnt,stp:longint;
- stat,x:word;
- begin
- stat:=crtc+6;
- disable;
- stp:=200000;
- cnt:=0;
-
- while not VRetrace and (stp>0) do dec(stp);
- while VRetrace and (stp>0) do dec(stp);
- while not VRetrace and (stp>0) do dec(stp);
-
- if stp>0 then
- for x:=1 to 5 do
- begin
- while VRetrace and (cnt<1000000) do inc(cnt);
- while not VRetrace and (cnt<1000000) do inc(cnt);
- end;
-
- enable;
- getticks:=cnt;
- end;
-
-
- procedure progICD2061reg(clk:longint);
- const
- ser_clk=4;
- ser_dta=8;
- var
- old,dta,bit:word;
- procedure setbits(bits:word);
- begin
- outp($3C2,bits);
- for bits:=1 to 5 do; {delay}
- end;
-
- begin
- if cv.chip=__S3 then {Needs to enable the ICD for the STB Pegasus...}
- begin
- outpw(crtc,$4838);
- outpw(crtc,$A539); {Enable S3 Ext}
- modinx(crtc,$42,$F,3);
- end;
- old:=inp($3CC);
- outpw(SEQ,$100);
- dta:=(old and $F3)+ser_dta;
- for bit:=1 to 6 do
- begin
- setbits(dta+ser_clk);
- setbits(dta);
- end;
- dta:=dta and $F3;
- setbits(dta);
- setbits(dta+ser_clk);
- setbits(dta);
- setbits(dta+ser_clk);
-
- for bit:=1 to 24 do
- begin
- dta:=dta and $F3;
- if (clk and 1)=0 then dta:=dta+ser_dta;
- setbits(dta+ser_clk);
- setbits(dta);
- dta:=dta xor ser_dta;
- setbits(dta);
- setbits(dta+ser_clk);
- clk:=clk shr 1;
- end;
- dta:=dta or ser_dta;
- setbits(dta+ser_clk);
- setbits(dta);
- setbits(dta+ser_clk);
- setbits(dta);
- outp($3C2,old);
- if cv.chip=__S3 then
- begin
- modinx(crtc,$5C,3,2);
- outpw(crtc,$5A39); {Disable S3 Ext}
- outpw(crtc,$38);
- end;
- outpw(SEQ,$300);
- delay(15);
- end;
-
-
- const
- clkperm:integer=0;
-
- function ClockPermission:boolean;
- begin
- if clkperm=0 then
- begin
- settextmode;
- writeln('WHATVGA is about to test the clock chip or crystals on your');
- writeln('board. This can cause strange behavior on the display.');
- writeln('If your monitor is fixed-frequency (MDA, CGA, EGA or original');
- writeln('VGA, in fact anything that can''t handle at least 800x600) this');
- writeln('could in extreme situations potentionally hurt your monitor.');
- writeln('Press Y to continue clock testing, any other key to skip it:');
- if (getkey and $DF)=ord('Y') then clkperm:=1
- else clkperm:=2;
- end;
- ClockPermission:=clkperm=1;
- end;
-
- procedure findclocks;
- var clks,x,y,divi,divid:word;
- basefreq,baselevel,l,l0,l1:longint;
- progcheck:boolean; {Should we check for programmable clocks??}
- begin
- if (inp($3CC) and 1)>0 then crtc:=$3D4 else crtc:=$3B4;
- progcheck:=true;
- clks:=4;
- case cv.clktype of
- clk_ext3:clks:=8;
- clk_ext4:clks:=16;
- clk_ext5:clks:=32;
- clk_ext6:clks:=64;
- clk_sdac:progcheck:=false;
- clk_TVP302x:begin
- progcheck:=false;
- clks:=0;
- end;
- end;
-
- if (clks>0) and ClockPermission then
- begin
- memmode:=_PL4;
- basefreq:=SetStdMode; {Usually mode 12h, but...}
- y:=getclk(divi,divid);
- baselevel:=getticks;
- if baselevel>0 then
- for x:=0 to clks-1 do
- begin
- if (x=8) and (cv.chip=__compaq) and (cv.version>=CPQ_QV) then
- vio($32); {Hack to get at last 8 clock of QVision}
- setclk(x,divid);
- delay(50); {Let clock settle}
- l:=getticks;
- if l>0 then cv.clks[x]:=((basefreq*baselevel) div l)*(divi div 12);
- end;
- setclk(y,divid);
- end;
- if progcheck and ClockPermission then
- begin
- outp($3C2,(inp($3CC) and $F3) or $8); {Clk 2}
- delay(150);
- progICD2061reg($C00000);
- progICD2061reg($41A83C); {14.318MHz* 2 * 109/62 = 50.35 MHz}
- l0:=getticks;
- progICD2061reg($41A8BC); {14.318MHz* 2/2 * 109/62 = 25.175 MHz}
- l1:=getticks;
-
- if (l0<>0) and (abs(l1-l0*2)<25) then
- begin {Found an ICD2061}
- cv.clktype:=clk_ICD2061;
- progICD2061reg($C04000); {Set prescale bit to *4}
- progICD2061reg($59A8BC); {14.318MHz* 4/2 * 109/62 = 50.35 MHz}
- l:=getticks;
- if abs(l1-l*2)<25 then {Prescale bit exists = ICD2061A}
- cv.clktype:=clk_ICD2061A;
- progICD2061reg($C00000); {Restore ?}
- end;
- setclk(y,divid);
- end;
-
- end;
-
-
- procedure SelectVideo(item:word);
- begin
- cv:=vid[item];
- loadmodes;
- video:=header[cv.chip];
- settextmode;
- end;
-
-
- procedure dac2pel; {Force DAC back to PEL mode}
- begin
- if inp($3c8)=0 then;
- end;
-
- function trigdac:word; {Reads $3C6 4 times}
- var x:word;
- begin
- x:=inp($3c6);
- x:=inp($3c6);
- x:=inp($3c6);
- if (cv.dactype=_dacMU1880) then x:=inp($3C6);
- trigdac:=inp($3c6);
- end;
-
- procedure dac2comm; {Enter command mode of HiColor DACs}
- begin
- dac2pel;
- daccomm:=trigdac;
- end;
-
- function getdaccomm:word;
- begin
- {if cv.DAC_RS2<>0 then getdaccomm:=inp($3C6+cv.DAC_RS2)
- else} begin
- dac2comm;
- getdaccomm:=inp($3C6);
- dac2pel;
- end;
- end;
-
- const
- SavedDACpage:word=0; {DAC page state saved by SaveDACpage, reset by clearDACpage}
-
- procedure SaveDACpage;
- begin
- SavedDACpage:=0; {default}
- if (cv.flags and FLG_ExtDAC)>0 then {RS2/3 addressing ?}
- case cv.chip of
- __S3:begin
- outpw(crtc,$4838); {Unlock S3 regs}
- outpw(crtc,$A539);
- SavedDACpage:=(rdinx(crtc,$43) and 2) shl 1;
- if (cv.version>S3_924) and (SavedDACpage=0) then
- SavedDACpage:=(rdinx(crtc,$55) and 3) shl 2;
- if (rdinx(crtc,$5C) and $20)>0 then inc(SavedDACpage,16);
- outpw(crtc,$5A39);
- outpw(crtc,$38); {Lock S3 regs}
- end;
- end;
- end;
-
-
- const
- DACpage:boolean=false; {Set if DAC registers enabled (MGA,Weitek..)}
-
- {Returns the address of the DAC register selected by index (0..3
- for standard DACs, 0..7 or 0..15 for advanced DACs), and sets
- any necessary flags. }
- function setDACpage(index:word):word;
- const
- DACadr:array[0..3] of word=($3C8,$3C9,$3C6,$3C7);
- M32DACadr:array[0..3] of word=($2EC,$2ED,$2EA,$2EB);
- var ret,x:word;
- found:boolean;
- begin
- found:=true;
- ret:=DACadr[index and 3];
- if cv.chip=__AGX then outp(cv.IOadr,1); {Enable VGA regs}
- if (cv.flags and FLG_ExtDAC)>0 then {RS2/3 addressing ?}
- case cv.chip of
- __AGX:begin
- if index>7 then ret:=cv.spcreg+(index and 3);
- if (index and 4)>0 then outp(cv.IOadr+10,$51)
- else outp(cv.IOadr+10,0);
- end;
- __ATI:if cv.Version<ATI_GUP_3 then found:=false
- else modinx(cv.IOadr,$A0,$60,index shl 3);
- __Compaq:begin
- if (index and 4)>0 then inc(ret,$8000);
- if (index and 8)>0 then inc(ret,$1000);
- end;
- __Mach32:begin
- { modinx(cv.IOadr,$A0,$60,index shl 3);}
- x:=inp($8EEF) and $CF;
- outp($7AEF,x+((index and $C) shl 2));
- ret:=ret-$DC; {3C8 -> 2EC}
- end;
- __Mach64:begin
- outp($62EC,index shr 2);
- ret:=$5EEC+(index and 3);
- end;
- __MGA:begin
- if (not DACpage) and (cv.PCIid>0) then
- begin
- wPCIlong($10,$AC000); {Map ACC regs at AC000h}
- cv.Xseg:=$AC00;
- DACpage:=true;
- end;
- ret:=0;
- end;
- __NCR:ret:=ret+((index and 4) shl 13); {A15 = $8000}
- __S3:begin
- outpw(crtc,$4838); {Unlock S3 regs}
- outpw(crtc,$A539);
- if cv.version>S3_924 then
- begin
- clrinx(crtc,$43,2); {Just in case}
- modinx(crtc,$55,3,index shr 2);
- modinx(crtc,$5C,$20,index shl 1); {TVP3025 control}
- end
- else modinx(crtc,$43,2,index shr 1);
- outpw(crtc,$5A39);
- outpw(crtc,$38); {Lock S3 regs}
- end;
- __Tseng:begin
- outp($3BF,3);
- outp(crtc+4,$A0);
- modinx(crtc,$31,$40,index shl 4); {Chrontel DAC}
- end;
- {Diamond Viper w/ OAK }
- __OAK:ret:=ret+(index and $C) shl 12;
- __Weitek,__WeitekP9:
- if (cv.version<WT_P9100) and (cv.PCIid=0) then
- ret:=ret+(index and $C) shl 12 {Non-PCI P9000s}
- else begin
- if not DACpage then
- begin
- outp($9100,$41);
- x:=inp($9104);
- outp($9100,$41);
- outp($9104,(x and $F3) or 4); {Enable Acc regs at A000h}
- DACpage:=true;
- end;
- ret:=0;
- end;
- else found:=false;
- end
- else found:=false;
- if not found and (index=dacHIcmd) then dac2comm;
- setDACpage:=ret;
- end;
-
- {Clears any bits set by setDACpage. Should be used after a sequence
- of extended DAC register accesses to avoid problems with accessess
- to the standard DAC registers}
- procedure clearDACpage;
- var x:word;
- begin
- if cv.chip=__AGX then outp(cv.IOadr,4); {Disable VGA regs}
- if SavedDACpage>0 then
- x:=setDACpage(SavedDACpage)
- else begin
- if (cv.flags and FLG_ExtDAC)>0 then {RS2/3 addressing ?}
- case cv.chip of
- __AGX:outp(cv.IOadr+10,0);
- __ATI:clrinx(cv.IOadr,$A0,$60);
- __Mach64:outp($62EC,0);
- __MGA:if DACpage then
- wPCIlong($10,PCIrec[cv.PCIid].l[4]);
- __S3:begin
- outpw(crtc,$4838); {Unlock S3 regs}
- outpw(crtc,$A539);
- if cv.version>S3_924 then clrinx(crtc,$55,3);
- clrinx(crtc,$43,2);
- outpw(crtc,$5A39);
- outpw(crtc,$38); {Lock S3 regs}
- end;
- __Tseng:begin
- outp($3BF,3);
- outp(crtc+4,$A0);
- clrinx(crtc,$31,$40); {Chrontel DAC}
- end;
- __Weitek,__WeitekP9:
- if DACpage then
- begin
- outp($9100,$41);
- x:=inp($9104);
- outp($9100,$41);
- outp($9104,x and $F3); {Disable Acc regs at A000h}
- end;
- else dac2pel;
- end
- else dac2pel;
- end;
- DACpage:=false;
- end;
-
-
-
- function rdDACreg(index:word):word;
- var inx:word;
- begin
- inx:=SetDACpage(index);
- if inx=0 then
- case cv.chip of
- __MGA:rdDACreg:=mem[cv.Xseg:$3C00+index*4];
- __Weitek,__WeitekP9:
- begin
- if mem[SegA000:$198]=0 then; {Wait ?}
- rdDACreg:=mem[SegA000:$200+4*index];
- end;
- end
- else rdDACreg:=inp(inx);
- end;
-
- procedure wrDACreg(index,val:word);
- var inx:word;
- begin
- inx:=SetDACpage(index);
- if inx=0 then
- case cv.chip of
- __MGA:mem[cv.Xseg:$3C00+index*4]:=val;
- __Weitek,__WeitekP9:
- mem[SegA000:$200+4*index]:=val;
- end
- else outp(inx,val);
- end;
-
-
- procedure clrDACreg(index,val:word);
- begin
- wrDACreg(index,rdDACreg(index) and not val);
- end;
-
- procedure setDACreg(index,val:word);
- begin
- wrDACreg(index,rdDACreg(index) or val);
- end;
-
- procedure modDACreg(index,msk,val:word);
- begin
- wrDACreg(index,(rdDACreg(index) and not msk) or (msk and val));
- end;
-
-
- function rgb(r,g,b:word):longint;
- begin
- r:=lo(r);g:=lo(g);b:=lo(b);
- case memmode of
- _PL1,_PL1E,_CGA1:
- rgb:=r and 1;
- _PL2,_CGA2:
- rgb:=r and 3;
- _PL4,_PK4:rgb:=r and 15;
- _P8:rgb:=r;
- _P15:rgb:=((r shr 3) shl 5+(g shr 3)) shl 5+(b shr 3);
- _P16:rgb:=((r shr 3) shl 6+(g shr 2)) shl 5+(b shr 3);
- _P24,_P32:rgb:=(longint(r) shl 8+g) shl 8 +b;
- _P24b,_P32b:rgb:=(longint(b) shl 8+g) shl 8 +r;
- _p32c:rgb:=((longint(r) shl 8+g) shl 8 +b) shl 8;
- _P32d:rgb:=((longint(b) shl 8+g) shl 8 +r) shl 8;
- end;
- end;
-
-
- {Writes a 32bit value to a DWORD at offset ADR in Xseg}
- procedure write32(adr:word;val:longint);
- var w:word;
- begin
- w:=cv.Xseg;
- {mov es,[cv.Xseg] mov di,[BP+adr] mov eax,[BP+val] mov es:[di],eax}
- inline($8E/$46/<w/$8B/$7E/<adr/$66/$8B/$46/<val/$66/$26/$89/5);
- end;
-
- {Writes a two 16bit values to a DWORD at offset ADR in Xseg as one MOVL}
- procedure write32w(adr:word;hiw,low:word);
- var w:word;
- l:longint;
- begin
- l:=(longint(hiw) shl 16)+low;
- w:=cv.Xseg;
- {mov es,[cv.Xseg] mov di,[BP+adr] mov eax,[BP+l] mov es:[di],eax}
- inline($8E/$46/<w/$8B/$7E/<adr/$66/$8B/$46/<l/$66/$26/$89/5);
- end;
-
-